package chat_client;

// -----------------------------------------------------------------------------
// Importanweisungen
import for_all.Message;
import for_all.PopUp;
import for_all.PrivateChat;
import for_all.Room;
import for_all.Room.UserChangedRoom;
import for_all.Transporter;
import for_all.User;
import for_all.User.LogOutUser;
import for_all.User.NewUserLoggedOn;
import for_all.User.UserLoggedOff;
import java.util.ArrayList;


public class ServerHandler extends Thread {
    
    // -------------------------------------------------------------------------
    // Variablendeklarationen
    private ArrayList<String> liste; // Wird zum Empfangen der Liste (Raum) gebraucht
    private Transporter transporter;
    private boolean     listeReady;  // Wird zum Empfangen der Liste (Raum) gebraucht
    private ClientGui  clientGui;
    private LogInGUI    logInGui;
    private User user;
    
    
    // -------------------------------------------------------------------------
    // Konstruktor
    public ServerHandler (Transporter transporter, ClientGui clientGUI) {
        
        this.transporter = transporter;
        this.clientGui = clientGUI;
        listeReady = false;
        
    }
    
    
    // -------------------------------------------------------------------------
    // Thread zum Verarbeiten von eingehenden Netzwerkkommunikationen
    @Override
    @SuppressWarnings("empty-statement")
    public void run () {
        
        while (!this.isInterrupted()) {
        
        Object receivedMessage = transporter.receiveObject();
            
            // Message empfangen und ausgeben
            if(receivedMessage instanceof Message) {
                                    
                this.clientGui.setMessage((Message) receivedMessage);
                
                
            // LogIn Rückmeldung    
            } else if (receivedMessage instanceof User.LogInAnswer) {
                   
                this.user.loginAnswer = (User.LogInAnswer) receivedMessage;
                synchronized (this) { notify(); };
               
                
            // User angemeldet
            } else if (receivedMessage instanceof NewUserLoggedOn) {
                NewUserLoggedOn nachricht = (NewUserLoggedOn)receivedMessage;
                this.clientGui.setUser(nachricht.getUserName(), nachricht.getRoomName(), true);
                
                
            // User abgemeldet
            } else if(receivedMessage instanceof UserLoggedOff) {
                UserLoggedOff nachricht = (UserLoggedOff)receivedMessage;
                this.clientGui.setUser(nachricht.getUserName(), nachricht.getRoomName(), true);
                
                
            // neuer User tritt Raum bei
            } else if (receivedMessage instanceof Room.newUserInRoom) {
                 
                Room dummy = new Room("dummy");
                dummy.setNewUserInRoom((Room.newUserInRoom)receivedMessage);
                clientGui.setNewUserInRoom(dummy.getNewUserInRoom().getName());
                
                
            // String-Liste für verschieden funktionen
            } else if (receivedMessage instanceof ArrayList) {
                
                if(liste != null) {
                    liste.clear();
                }
                
                ArrayList<String> empfangsliste = (ArrayList<String>) receivedMessage;
                this.liste = empfangsliste;
                listeReady = true;
                
                
            // User verlässt Raum
            } else if(receivedMessage instanceof Room.userLeavedRoom) {
                
                Room dummy = new Room("dummy");
                dummy.setUserLeavedRoom((Room.userLeavedRoom)receivedMessage);
                clientGui.setUserLeavedRoom(dummy.getUserLeavedRoom().getName());
                
                
            // Raumname wurde geändert
            } else if(receivedMessage instanceof Room.roomNameChanged) {
                
                Room dummy = new Room("dummy");
                dummy.setRoomNameChanged((Room.roomNameChanged)receivedMessage);
                clientGui.setRoomNameChanged(dummy.getRoomNameChanged().getOldName(), dummy.getRoomNameChanged().getNewName());
                
                
            // Neuer Raum
            } else if(receivedMessage instanceof Room.roomCreated) {
                
                Room dummy = new Room("dummy");
                dummy.setRoomCreated((Room.roomCreated)receivedMessage);
                clientGui.setNewRoomCreated(dummy.getRoomCreated().getRoomName());
                
                
            // Raum wurde gelöscht
            } else if(receivedMessage instanceof Room.roomDeleted) {
              
                Room dummy = new Room("dummy");
                dummy.setRoomDeleted((Room.roomDeleted)receivedMessage);
                clientGui.setRoomDeleted(dummy.getRoomDeleted().getRoomName());
                
                
            // Wenn ein Nutzer seinen Raum gewechselt hat
            } else if(receivedMessage instanceof UserChangedRoom) {
                
                UserChangedRoom nachricht = (UserChangedRoom)receivedMessage;
                clientGui.changeUsersRoom(nachricht.getUserName(), nachricht.getRoomName());
                
                
            // Server wurde beendet
            } else if(receivedMessage instanceof User.LogOutUser) {
                
                LogOutUser logout = (LogOutUser) receivedMessage;
                HandleLogout(logout.getReason());
                
                
            // neuer Privater Chat mit diesem User als Partner wurde eingerichtet
            } else if (receivedMessage instanceof PrivateChat.informAboutNewPrivateChat) {
                
                this.clientGui.setNewPrivateChat(((PrivateChat.informAboutNewPrivateChat)receivedMessage).otherUser);
                
                
            // private Chat mit diesem User wurde beendet
            } else if (receivedMessage instanceof PrivateChat.RemovePrivateChat){
                
                this.clientGui.removePrivateChatTab(((PrivateChat.RemovePrivateChat)receivedMessage).otherUser, false);
                
            }
        }
    }   // run    

    // beendet den Client und gibt Nachricht aus Warum
    private void HandleLogout(LogOutUser.LogoutReason reason) {
        switch(reason) {
            case ServerClosed: PopUp nachricht1 = new PopUp(clientGui, "Sie wurden ausgeloggt, da der Server geschlossen wurde.", "Sie wurden ausgeloggt", PopUp.MessageTyp.Information); break;
            case Banned: PopUp nachricht2 = new PopUp(clientGui, "Sie wurden ausgeloggt, da sie vom Admin vom Server gebannt wurden.", "Sie wurden ausgeloggt", PopUp.MessageTyp.Warning); break;
            case Kicked: PopUp nachricht3 = new PopUp(clientGui, "Sie wurden ausgeloggt, da der Admin ihre Verbindung getrennt hat.", "Sie wurden ausgeloggt", PopUp.MessageTyp.Warning); break;
        }
        
        this.stopClient();
    }
    
    // -------------------------------------------------------------------------
    // LogIn an Server
    public synchronized boolean logIn() throws InterruptedException {
       
        // 1. LogIn Fenster aufrufen und Eingabe auslesen
        this.logInGui = new LogInGUI(this.clientGui,true);
        this.logInGui.setVisible(true);


        this.user = this.logInGui.getUser();
        
        
        // 2. LogIn Anfrage an Server senden und auf Antwort warten
        this.transporter.sendObject(this.user);
        synchronized (this) { wait(); }
            
        
        // 3. Antwort des Servers (Begrüßung/Fehlermeldung) ausgeben
        //    und Rückgabewert setzen
        this.user.loginAnswer.ThrowMessage(this.clientGui);
           
        // Rückgabewert
        if (this.user.loginAnswer.getStatus() ==  User.LoginResult.accepted ||  this.user.loginAnswer.getStatus() == User.LoginResult.nonRegistrated ) {
            
            for (int i = 0; i < this.user.loginAnswer.onlineUserList.length; i++) {
                if (this.user.loginAnswer.onlineUserList[i] != null) {
                    this.clientGui.setUser(this.user.loginAnswer.onlineUserList[i], this.user.loginAnswer.rooms[i], false);
                }
            }
            
            return true;
        } else {
            return false;
        }
        
    }
    
    
    // -------------------------------------------------------------------------
    // Client herunterfahren
    public void stopClient() {
        
        this.interrupt();
        this.transporter.close();
        System.exit(0);

    }
    
    
    // -------------------------------------------------------------------------
    // gibt den User zurück
    public User getUser() {
        return this.user;
    }
    
    
    // -------------------------------------------------------------------------
    // gibt den Transporter zurück
    public Transporter getTransporter() {
        return transporter;
    }
    
    
    // -------------------------------------------------------------------------
    // eine Raum beitreten und alle User darin zurückliefern
    public ArrayList<String> joinRoom(String roomName) throws InterruptedException {
        
        Room dummy = new Room("dummy");
        dummy.setUserJoinsRoom(roomName, user.getUserName());
        
        transporter.sendObject(dummy.getuserJoinsRoom());
        
        while(!listeReady) {
            Thread.sleep(10);
        }
        
        listeReady = false;   //für die Zukunft vielleicht semaphore verwenden
        
        return liste;
    }
    
    
    // -------------------------------------------------------------------------
    // Liste vom Server erhalten, die Liste aller Räume enthält
    public synchronized ArrayList<String> getRoomNames() throws InterruptedException {
        
        Room dummy = new Room("dummy");
        dummy.setGetRoomNames(user.getUserName());
        
        transporter.sendObject(dummy.getGetRoomNames());
        
        while(!listeReady) {
            Thread.sleep(10);
        }
        
        listeReady = false;
        return liste;
    }
    
    
    // -------------------------------------------------------------------------
    // Message an Server senden
    public void sendMessage(Message msg) {
        transporter.sendObject(msg);
    }
    
    
    // -------------------------------------------------------------------------
    // privaten Chat initiieren
    public PrivateChat initiatePrivateChat(String otherUser) {
        
        PrivateChat prch = new PrivateChat(this.user.getUserName(), otherUser);
        
        this.transporter.sendObject(prch);
        return prch;
        
    }
    
    
    // -------------------------------------------------------------------------
    // entfernen von privaten Chat
    public void removePrivateChat(String otherUser) {
        
        PrivateChat prch = new PrivateChat(this.user.getUserName(), otherUser);
        
        this.transporter.sendObject(prch.getDeleteMessage(otherUser));
        
    }
}